import {
    PropDataType,
    DATA_TYPE_TO_INPUT_WIDGETS,
    FORM_WIDGETS,
    DATA_TYPE,
    FieldType,
} from "@/components/dynamicform/formdatastruct"
/* Validation include two parts:
 *   1. The el-form support a property: 'rules'. It supply the basic validation,
 *      like: number type, date type... But if I want to write a json field, it 
 *      failed.
 *   2. Validate at 'watch userInputForm', and put the errors in this.errors
*/
// validation rules
function getFieldRequiredValidator(key: string, field: PropDataType): Record<string, unknown> {
    let v: Record<string, unknown> = {}
    if (field.Required) {
        v = { required: field.Required ? true : false, message: '请输入' + key }
    }
    return v
}
function getFieldTypeValidator(key: string, field: PropDataType): Record<string, unknown> {
    let v: Record<string, unknown> = {}
    switch (DATA_TYPE_TO_INPUT_WIDGETS[field.Type]) {
        case FORM_WIDGETS.INPUT:
            if (field.Type === DATA_TYPE.signal) {
                v.validator = (_: unknown, value: FieldType, callback: any) => {
                    SignalTypeValidator(field, value, callback)
                }
            } else if (field.Type !== DATA_TYPE.string) {
                v.validator = (_: unknown, value: FieldType, callback: any) => {
                    NumberTypeValidator(field, value, callback)
                }
            }
            break
        case FORM_WIDGETS.JSON:
            v.validator = (_: unknown, value: FieldType, callback: any) => {
                jsonFieldValidator(field, value, callback)
            }
            break
        /*case FORM_WIDGETS.DATETIME:
            v = {
                type: 'datetime',
                message: 'Please pick a datetime',
                trigger: 'change',
              }
            break*/
        case FORM_WIDGETS.DATE:
            v = {
                type: 'date',
                message: 'Please pick a date',
                trigger: 'change',
            }
            break
    }
    return v
}



// type validator
function NumberTypeValidator(field: PropDataType, value: FieldType, callback: any): void {
    const type = field.Type
    const value_ = Number(value.Value)
    if (Number.isNaN(value_)) { callback(new Error("值应为数字")) }
    const floor = Math.floor(value_)
    switch (type) {
        case DATA_TYPE.uint:
            if (value_ < 0) { callback(new Error("值不为非负整数")) }
            if (value_ === floor) { callback() }
            else { callback(new Error("值不为整数")) }
            return
        case DATA_TYPE.int:
            if (value_ === floor) { callback() }
            else { callback(new Error("值不为整数")) }
            return
    }
    callback()
}
// type validator
function SignalTypeValidator(field: PropDataType, value: FieldType, callback: any): void {
    const type = field.Type
    try {
        const value_ = eval(value.Value as string)
    } catch (e) {
        callback(new Error("求值失败，无法转换为信号类型"))
    }
    callback()
}


// json field validator. required true no repeat
function jsonFieldValidator(field: PropDataType, value: FieldType, callback: any): void {
    const vList = value.Value as unknown[][]
    for (const i in vList) {
        const pairs = vList[i]
        if (pairs[0] == null) {
            callback(new Error("key不能为空"))
        }
        if (pairs[1] == null) {
            callback(new Error("value不能为空"))
        }
    }
}
function getFieldRules(key: string, field: PropDataType): Array<Record<string, unknown>> {
    //return [getFieldRequiredValidator(key, field), getFieldTypeValidator(key, field)]

    const fieldrules = []
    const requiredrules = getFieldRequiredValidator(key, field)
    const typerules = getFieldTypeValidator(key, field)

    if (requiredrules && Object.keys(requiredrules).length !== 0) {
        fieldrules.push(requiredrules)
    }
    if (typerules && Object.keys(typerules).length !== 0) {
        fieldrules.push(typerules)
    }
    return fieldrules
}
// validate at watch and rewrite errors
function FieldsValidation(
    dataForm: Record<string, FieldType>
): Record<string, (string | null)[]> {
    const errors: Record<string, (string | null)[]> = {}
    for (const key in dataForm) {
        if (dataForm[key].Type === DATA_TYPE.json) {
            errors[key] = []
            const vList = dataForm[key].Value as string[][]
            const existKeys: string[] = []
            for (const i in vList) {
                errors[key][i] = null
                const pair = vList[i]
                if (pair[0] == null || pair[0] == "") {
                    errors[key][i] = "key不能为空"
                } else if (pair[1] == null || pair[1] == "") {
                    errors[key][i] = "value不能为空"
                } else if (existKeys.indexOf(pair[0]) >= 0) {
                    errors[key][i] = "key重复"
                } else {
                    existKeys.push(pair[0])
                }
            }
        }
    }
    return errors
}
export { getFieldRules, FieldsValidation }